<?php
    /**
     *加密字符串
     *
     *
     * @author      libin<hansen.li@silksoftware.com>
     * @version     1.0
     * @since       1.0
     */

    namespace app\common\utils;
    use Rhumsaa\Uuid\Uuid;

    /**
     * Class UtilEncryption
     *
     * @package app\common\utils
     */
    class UtilEncryption
    {

        /**
         * 采用HashHmac方法获取加密的字符串
         *
         * @param unknown $data   需要加密的字符串
         * @param string  $secret 加密秘钥
         *
         * @return string|boolean
         */
        public static function encryptHashHmac($data,$secret = "")
        {

            return base64_encode(hash_hmac('sha256',$data,$secret,$raw = false));
        }

        /**
         * 采用md5方法获取加密的字符串
         *
         * @param unknown $data   需要加密的字符串
         * @param string  $secret 加密秘钥
         *
         * @return string|boolean
         */
        public static function encryptMd5($data,$secret = "")
        {

            return md5(md5($data . $secret) . $secret);
        }

        /**
         * 生成随机字符串
         *
         * @param     $param
         * @param int $lenth
         *
         * @return string
         */
        public static function getRandom($param,$lenth = 32)
        {

            $str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
            $key = "";
            for ($i = 0; $i < $param; $i++)
            {
                $key .= $str{mt_rand(0,$lenth)};    //生成php随机数
            }
            return $key;
        }

        /**
         * 取得随机数,并可指定长度
         *
         * @param int $length  生成随机数的长度
         * @param int $numeric 是否只产生数字随机数 1是0否
         *
         * @return string
         */
        static function random($length,$numeric = 0)
        {

            $seed = base_convert(md5(microtime() . $_SERVER['DOCUMENT_ROOT']),16,$numeric ? 10 : 35);
            $seed = $numeric ? (str_replace('0','',$seed) . '012340567890') : ($seed . 'zZ' . strtoupper($seed));
            $hash = '';
            $max  = strlen($seed) - 1;
            for ($i = 0; $i < $length; $i++)
            {
                $hash .= $seed{mt_rand(0,$max)};
            }
            return $hash;
        }

        /**
         * 生成指定长度字随机
         *
         * @param int $length 指定长度
         *
         * @return int
         */
        static public function RandomNumber($length = 6)
        {

            return rand(pow(10,($length - 1)),pow(10,$length) - 1);
        }


        /**
         * Created by PhpStorm.
         * User: envon
         * Date: 2016/10/27
         * Time: 17:17
         */


        //开始时间,固定一个小于当前时间的毫秒数即可
        const twepoch = 1474992000000;//2016/9/28 0:0:0

        //机器标识占的位数
        const workerIdBits = 10;

        //毫秒内自增数点的位数
        const sequenceBits = 12;

        static protected $workId = 0;

        //要用静态变量
        static protected $lastTimestamp = -1;

        static protected $sequence = 0;

        static function UniqueID($workId = 5)
        {

            //机器ID范围判断
            $maxWorkerId = -1 ^ (-1 << self::workerIdBits);
            if ($workId > $maxWorkerId || $workId < 0)
            {
                throw new \Exception("workerId can't be greater than " . self::maxWorkerId . " or less than 0");
            }
            //赋值
            static::$workId = $workId;
            return static::nextId();
        }

        //生成一个ID
        static protected function nextId()
        {

            $timestamp     = static::timeGen();
            $lastTimestamp = self::$lastTimestamp;
            //判断时钟是否正常
            if ($timestamp < $lastTimestamp)
            {
                throw new \Exception("Clock moved backwards.  Refusing to generate id for %d milliseconds",($lastTimestamp - $timestamp));
            }
            //生成唯一序列
            if ($lastTimestamp == $timestamp)
            {
                $sequenceMask   = -1 ^ (-1 << self::sequenceBits);
                self::$sequence = (self::$sequence + 1) & $sequenceMask;
                if (self::$sequence == 0)
                {
                    $timestamp = static::tilNextMillis($lastTimestamp);
                }
            }
            else
            {
                self::$sequence = 0;
            }
            self::$lastTimestamp = $timestamp;
            //
            //时间毫秒/数据中心ID/机器ID,要左移的位数
            $timestampLeftShift = self::sequenceBits + self::workerIdBits;
            $workerIdShift      = self::sequenceBits;
            //组合3段数据返回: 时间戳.工作机器.序列
            $nextId = (($timestamp - self::twepoch) << $timestampLeftShift) | (static::$workId << $workerIdShift) | self::$sequence;
            return $nextId;
        }

        //取当前时间毫秒
        static protected function timeGen()
        {

            $timestramp = (float)sprintf("%.0f",microtime(true) * 1000);
            return $timestramp;
        }

        //取下一毫秒
        static protected function tilNextMillis($lastTimestamp)
        {

            $timestamp = static::timeGen();
            while ($timestamp <= $lastTimestamp)
            {
                $timestamp = static::timeGen();
            }
            return $timestamp;
        }

        static public function test()
        {

            //调用
            header("Content-Type: text/html; charset=utf-8");
            $work = new self(1023);
            for ($i = 0; $i < 10; $i++)
            {
                $id = $work->nextId();
                echo $id . "<br>";
            }
        }

        /**
         * 生成唯一单编号(两位随机 + 从2000-01-01 00:00:00 到现在的秒数+微秒+会员ID%1000)，该值会传给第三方支付接口
         * 长度 =2位 + 10位 + 3位 + 3位  = 18位
         * 1000个会员同一微秒提订单，重复机率为1/100
         * @return string
         */
        static public function MakeSn($prefix = '')
        {
            if($prefix){
                return $prefix . '_' . static::uuid1();
            }
            return static::uuid1();
        }

        static function guid($factor = '', $prefix = '', $suffix = '')
        {
            list($usec, $sec) = explode(" ", microtime());
            $guid = $prefix . $factor
                . $sec . $usec
                . mt_rand(0, 1000000) . time() . mt_rand(0, 1000000) . $suffix;
            $guid = substr(md5($guid), 8, 16);
            $guid = strtoupper(base_convert($guid, 16, 36));
            $guid = str_pad($guid, 13, '0', STR_PAD_LEFT);
            return $prefix . $guid . $suffix;
        }

        /**
         *  Generate a version 1 (time-based) UUID object
         * 生成版本1（基于时间）的UUID对象
         * @return string
         */
        static function uuid1()
        {
            return Uuid::uuid1()->toString(); // i.e. e4eaaaf2-d142-11e1-b3e4-080027620cdd
        }

        /**
         * Generate a version 3 (name-based and hashed with MD5) UUID object
         * 生成版本3（基于名称并使用MD5进行散列）UUID对象
         * @param Uuid $constant
         * @param $string
         * @return string
         */
        static function uuid3(Uuid $constant, $string)
        {
            return Uuid::uuid3($constant, $string)->toString(); // i.e. e4eaaaf2-d142-11e1-b3e4-080027620cdd
        }

        /**
         * Generate a version 4 (random) UUID object
         * 生成版本4（随机）UUID对象
         * @return string
         */
        static function uuid4()
        {
            return Uuid::uuid4()->toString(); // i.e. e4eaaaf2-d142-11e1-b3e4-080027620cdd
        }

        /**
         * Generate a version 5 (name-based and hashed with SHA1) UUID object
         * 生成版本5（基于名称并使用SHA1散列）UUID对象
         * @param Uuid $constant
         * @param $string
         * @return string
         */
        static function uuid5(Uuid $constant, $string)
        {
            return Uuid::uuid5($constant, $string)->toString(); // i.e. e4eaaaf2-d142-11e1-b3e4-080027620cdd
        }
    }
